
/**		
 * 
 *	uk.co.lmfm.guppy.model.SVNAdobeProxy
 *	
 *	@version 1.00 | Jan 29, 2010
 *	@author Justin Windle
 *  
 **/
 
package uk.co.lmfm.guppy.model 
{
	import uk.co.lmfm.guppy.application.enum.ApplicationConstants;
	import uk.co.lmfm.guppy.model.vo.FlexSDKVO;

	import org.osflash.thunderbolt.Logger;
	import org.puremvc.as3.multicore.interfaces.IProxy;
	import org.puremvc.as3.multicore.patterns.proxy.Proxy;

	import flash.desktop.NativeProcess;
	import flash.desktop.NativeProcessStartupInfo;
	import flash.events.Event;
	import flash.events.IOErrorEvent;
	import flash.events.NativeProcessExitEvent;
	import flash.events.ProgressEvent;
	import flash.filesystem.File;
	import flash.filesystem.FileMode;
	import flash.filesystem.FileStream;
	import flash.net.URLLoader;
	import flash.net.URLLoaderDataFormat;
	import flash.net.URLRequest;
	import flash.utils.ByteArray;

	/**
	 * SVNAdobeProxy
	 */
	public class AdobeOSProxy extends Proxy implements IProxy 
	{
		//	----------------------------------------------------------------
		//	CONSTANTS
		//	----------------------------------------------------------------

		public static const NAME : String = "SVNAdobeProxy";

		private static const UNZIP_PATH : String = "/usr/bin/unzip";

		//	----------------------------------------------------------------
		//	PRIVATE MEMBERS
		//	----------------------------------------------------------------

		private var _queue : Vector.<FlexSDKVO> = new Vector.<FlexSDKVO>();		private var _sdks : Vector.<FlexSDKVO> = new Vector.<FlexSDKVO>();
		private var _loader : URLLoader = new URLLoader();
		private var _unzipProcess : NativeProcess = new NativeProcess();
		private var _current : FlexSDKVO;
		private var _tempZip : File;
		private var _sdkFolder : File;		private var _destination : File;
		private var _lastProgress : Number;
		private var _progress : Number;
		private var _completed : int;		private var _numItems : int;

		//	----------------------------------------------------------------
		//	CONSTRUCTOR
		//	----------------------------------------------------------------

		public function AdobeOSProxy(data : Object = null)
		{
			super(NAME, data);
		}

		//	----------------------------------------------------------------
		//	PUBLIC METHODS
		//	----------------------------------------------------------------

		override public function onRegister() : void
		{
			super.onRegister();
			
			_loader.dataFormat = URLLoaderDataFormat.BINARY;
			_loader.addEventListener(ProgressEvent.PROGRESS, onLoaderProgress);
			_loader.addEventListener(IOErrorEvent.IO_ERROR, onLoaderError);
			_loader.addEventListener(Event.COMPLETE, onLoaderComplete);
		}

		public function downloadSDKs(sdks : Vector.<FlexSDKVO>, libraryPath : String) : void
		{
			_queue = sdks.concat();
			_sdks = sdks.concat();
			_numItems = sdks.length;
			_progress = _lastProgress = _completed = 0.0;
			_sdkFolder = new File().resolvePath(libraryPath).resolvePath("SDK");
			sendNotification(ApplicationConstants.CHECKOUT_MESSAGE, "Retrieving SDK list...");
			downloadNextSDK();
		}

		//	----------------------------------------------------------------
		//	PRIVATE METHODS
		//	----------------------------------------------------------------

		private function downloadNextSDK() : void
		{
			if(_queue.length == 0)
			{
				sendNotification(ApplicationConstants.CHECKOUT_MESSAGE, "SDK Download Complete!");
				sendNotification(ApplicationConstants.SDK_DOWNLOAD_COMPLETE, _sdks);
				
				return;
			}
			
			_current = _queue.shift();
			
			_loader.load(new URLRequest(_current.url));
			sendNotification(ApplicationConstants.CHECKOUT_ITEM_STARTED, _current.id);
		}

		private function unzipFile(source : File, destination : File) : void
		{
			_destination = destination;
			
			if(NativeProcess.isSupported)
			{
				if(destination.exists) destination.deleteDirectory(true);
				destination.createDirectory();
				
				sendNotification(ApplicationConstants.CHECKOUT_MESSAGE, "Extracting: " + destination.nativePath);
				
				var unzipInfo : NativeProcessStartupInfo = new NativeProcessStartupInfo();
				
				unzipInfo.executable = new File(UNZIP_PATH);
				unzipInfo.arguments = new Vector.<String>();
				unzipInfo.workingDirectory = destination;
				unzipInfo.arguments.push(source.nativePath);

				_unzipProcess.addEventListener(NativeProcessExitEvent.EXIT, onUnzipComplete);
				_unzipProcess.addEventListener(ProgressEvent.STANDARD_OUTPUT_DATA, onUnzipProgress);				_unzipProcess.addEventListener(ProgressEvent.STANDARD_INPUT_PROGRESS, onUnzipProgress);				_unzipProcess.addEventListener(ProgressEvent.STANDARD_ERROR_DATA, onUnzipError);
				_unzipProcess.start(unzipInfo);
			}
		}

		private function onUnzipError(event : ProgressEvent) : void
		{
			Logger.error("Unzip error: " + _unzipProcess.standardError.readUTFBytes(_unzipProcess.standardError.bytesAvailable));
		}

		private function onUnzipComplete(event : NativeProcessExitEvent) : void
		{
			sendNotification(ApplicationConstants.CHECKOUT_MESSAGE, "Unzip complete...");
			_tempZip.deleteFile();
			
			var junk : File = _destination.resolvePath("__MACOSX");
			if(junk.exists) junk.deleteDirectory(true);
			
			downloadNextSDK();
		}

		private function onUnzipProgress(event : ProgressEvent) : void
		{
			var prog : String = _unzipProcess.standardOutput.readUTFBytes(_unzipProcess.standardOutput.bytesAvailable);
			sendNotification(ApplicationConstants.CHECKOUT_ACTIVITY, prog);
		}

		//	----------------------------------------------------------------
		//	EVENT HANDLERS
		//	----------------------------------------------------------------

		private function onLoaderProgress(event : ProgressEvent) : void
		{
			var itemProgress : Number = event.bytesLoaded / event.bytesTotal;
			
			_progress += itemProgress - _lastProgress;
			_lastProgress = itemProgress;
			
			sendNotification(ApplicationConstants.CHECKOUT_ITEM_PROGRESS, itemProgress);
			sendNotification(ApplicationConstants.CHECKOUT_PROGRESS, _progress / _numItems);
		}

		private function onLoaderError(event : IOErrorEvent) : void
		{
			Logger.error("Error downloading SDK:" + event.text);
		}

		private function onLoaderComplete(event : Event) : void
		{
			var filename : String = new Date().getTime() + ".zip";			_tempZip = File.applicationStorageDirectory.resolvePath(filename);
			
			try
			{
				if(_tempZip.exists) _tempZip.deleteFile();
				
				var stream : FileStream = new FileStream();
				var bytes : ByteArray = ByteArray(_loader.data);
				
				stream.open(_tempZip, FileMode.WRITE);
				stream.writeBytes(bytes, 0, bytes.length);
				stream.close();
				
				//Logger.info("File downloaded successfuly: " + _current.url);
				
				sendNotification(ApplicationConstants.CHECKOUT_ITEM_COMPLETE, _current.url);
				unzipFile(_tempZip, _sdkFolder.resolvePath(_current.id));
			}
			catch(error : ArgumentError)
			{
				Logger.error("Error saving file:" + error.message);
			}
			
			_completed++;
			_lastProgress = 0;
		}
	}
}
